package com.hjj.hello.spring.boot.shiro;

import com.hjj.hello.spring.boot.domain.User;
import com.hjj.hello.spring.boot.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

/**
 *
 * 自定义Realm
 * @author hjj
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 执行授权逻辑
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("=================执行授权逻辑===================");
        //给资源进行授权
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //添加资源的授权字符串
        //simpleAuthorizationInfo.addStringPermission("user:add");
        //从数据库查询用户的授权字符串
        //获取当前登录用户 --> 认证成功返回的 user
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        User dbuser = userService.selectById(user.getId());
        //添加从数据库查询用户的授权字符串
        simpleAuthorizationInfo.addStringPermission(dbuser.getPermission());
        return simpleAuthorizationInfo;
    }


    /**
     * 执行认证逻辑
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("=================执行认证逻辑===================");
        //编写 Shiro 的判断逻辑 , 判断用户名和密码
        //从数据库中查询到用户名和密码

        //获取controller 传过来的 token
        UsernamePasswordToken tokens = (UsernamePasswordToken)token;
        User user = userService.selectByUsername(tokens.getUsername());

        //用户名不存在 , 认证失败
        if(user == null){
            return null;// 此时返回null , shiro 底层会抛出 UnknownAccountException 异常
        }
        //用户名存在 再比对密码
        return new SimpleAuthenticationInfo(user,user.getPassword() ,"");//参数分别为: 返回到controller中login方法的返回值 ; 数据库中查询出的密码, shiro可自动判断 ; realmName
    }
}
